;
; TESTROM.MAC - A ROM to test the Colecovision Keyboard with
;

.Z80
ASEG

	ORG	100H

	INCLUDE	CVKBD.INC

;
; VDP register values
;

PATGEN	EQU	0
PATCOL	EQU	8*1024
PATNAM	EQU	6*1024
SPRATT	EQU	16*1024-128
SPRGEN	EQU	14*1024

.PHASE 08000H

BASE:	DB	0AAH,055H
	DW	0
	DW	0
	DW	0
	DW	0
	DW	START
	JP	RST08V
	JP	RST10V
	JP	RST18V
	JP	RST20V
	JP	RST28V
	JP	RST30V
	JP	RST38V
	JP	NMIV
; 08024H
	DB	'COLECOVISION KEYBOARD '
	DB	'/'
	DB	'TEST ROM/2013'
;
MSGINI:	DB	' Colecovision                   '
	DB	' Keyboard                       '
	DB	' Test ROM              @2013 #$ '
	DB	' ------------------------------ '
MSGKNF:	DB	' Keyboard not found             '
MSGKIS:	DB	' Keyboard initialising          '
MSGKIE:	DB	' Keyboard initialised           '
MSGKDN:	DB	' Pressed  '
MSGKUP:	DB	' Released '
;
; Main entry routine
;
START:	CALL	SNDOFF

; video registers
	LD	DE,0*100H+010B		; Grf Mode II
	CALL	VOUTRG
	LD	DE,1*100H+0C2H		; bit 6 => on, bit 5 => ints disabled
	CALL	VOUTRG
	LD	DE,2*100H+PATNAM/0400H
	CALL	VOUTRG
	LD	DE,3*100H+PATCOL/0040H+127
	CALL	VOUTRG
	LD	DE,4*100H+PATGEN/0800H+3
	CALL	VOUTRG
	LD	DE,5*100H+SPRATT/0080H
	CALL	VOUTRG
	LD	DE,6*100H+SPRGEN/0800H
	CALL	VOUTRG
	LD	DE,7*100H+1
	CALL	VOUTRG

; setup characters in each 1/3 of the screen
	LD	HL,CHARSET
	LD	DE,PATGEN
	LD	BC,256*8
	CALL	VCOPY
	LD	HL,CHARSET
	LD	DE,PATGEN+256*8
	LD	BC,256*8
	CALL	VCOPY
	LD	HL,CHARSET
	LD	DE,PATGEN+512*8
	LD	BC,256*8
	CALL	VCOPY

; every character is white on black
	LD	A,0F1H
	LD	DE,PATCOL
	LD	BC,3*256*8
	CALL	VSET

; initially no writing on the top 2/3 of the screen
	LD	A,' '
	LD	DE,PATNAM
	LD	BC,32*16
	CALL	VSET

; bottom 1/3 shows all characters
	LD	DE,PATNAM+16*32
	CALL	VSETOT
	LD	B,0	; = 256
	LD	C,0
ALLCH:	CALL	VDOUTP
	INC	C
	DJNZ	ALLCH

; no sprites visible
	LD	DE,SPRATT
	CALL	VSETOT
	LD	C,0D0H
	CALL	VDOUTP

; sign-on
	LD	HL,MSGINI
	LD	DE,PATNAM
	LD	BC,4*32
	CALL	VCOPY
;
; Keyboard present?
;
	CALL	KB_HW
	JR	Z,GOTKBD
;
	LD	HL,MSGKNF
	LD	DE,PATNAM+6*32
	LD	BC,32
	CALL	VCOPY
STOP:	JR	STOP
;
; Initialise the keyboard
;
GOTKBD:
	LD	HL,MSGKIS
	LD	DE,PATNAM+6*32
	LD	BC,32
	CALL	VCOPY
;
	CALL	KB_INIT
;
	LD	HL,MSGKIE
	LD	DE,PATNAM+6*32
	LD	BC,32
	CALL	VCOPY
;
; Main test loop
;
LOOP:	CALL	KB_GET
	CP	KD_RELE
	JR	Z,RELE
; its a press
	CALL	KDOWN
	CALL	KB_NEXT
	JR	LOOP
; its a release
RELE:	CALL	KB_NEXT
	CALL	KB_GET
	PUSH	AF
	CALL	KUP
	CALL	KB_NEXT
	POP	AF
	CP	'i'
	JR	Z,INKEY
	JR	LOOP
;
; Another loop
;
INKEY:	LD	HL,0
;
LOOP2:	PUSH	HL
	CALL	KB_PEEK
	POP	HL
	CP	KD_NONE
	JR	Z,NOKEY
; keyboard event ready
	CP	KD_RELE
	JR	Z,RELE2
; its a press
	PUSH	HL
	CALL	KDOWN
	CALL	KB_NEXT
	POP	HL
	JR	LOOP2
; its a release
RELE2:	PUSH	HL
	CALL	KB_NEXT
	CALL	KB_GET
	CALL	KUP
	CALL	KB_NEXT
	POP	HL
	JR	LOOP2
; no keyboard event ready at this time
NOKEY:	PUSH	HL
	LD	DE,PATNAM+12*32+8
	CALL	VSETOT
	CALL	SHOWW		; output HL
	POP	HL
	INC	HL
	JR	LOOP2

;
; KDOWN - keycode has been pressed
;
KDOWN:	PUSH	AF
	LD	HL,MSGKDN
	CALL	SHOWKC
	POP	AF
; show key press in lower 3rd of screen
	LD	C,0F8H		; white on medium red
	JP	SHOWKS
;
; KUP - keycode has been released
;
KUP:	PUSH	AF
	LD	HL,MSGKUP
	CALL	SHOWKC
	POP	AF
; remove key press from lower 3rd of screen
	LD	C,0E2H		; grey on medium green
	JP	SHOWKS
;
; Show keycode A, preceeded by 10 character message at HL
;
SHOWKC:	PUSH	AF
	LD	DE,PATNAM+8*32
	LD	BC,10
	CALL	VCOPY
	POP	AF
	JP	SHOWB
;
; Show keystatus keycode for A, highlighted in colour C
;
SHOWKS:	LD	L,A
	LD	H,0
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
	LD	DE,PATCOL+512*8
	ADD	HL,DE
	EX	DE,HL
	LD	A,C
	LD	BC,8
	JP	VSET
;
; Is there a keyboard attached
;
KB_HW:	IN	A,(P_KBD)
	LD	B,A
	IN	A,(P_KBD+1)
	CP	B
	RET	NZ
	IN	A,(P_KBD+2)
	CP	B
	RET	NZ
	IN	A,(P_KBD+3)
	CP	B
	RET	NZ
; all 4 ports return the same value, which is good
; if nothing was there, each IN returns the last thing put on the bus
; this would be the last byte of the opcode, P_KBD+x, different each time
	INC	A
	JR	NZ,KB_HW2
	DEC	A		; NZ => not present
	RET
; didn't get a HI-Z response
; if nothing was there, the bus could float high
KB_HW2:	XOR	A		; Z => present
	RET
;
; Initialise the keyboard
;
KB_INIT:
	LD	A,KC_INIT
	OUT	(P_KBD),A	; send init
KB_INI2:
	CALL	KB_INP		; wait until its done
	CP	KD_INIT
	JR	NZ,KB_INI2
	RET
;
; Peek the next available keycode
; Returns KD_NONE if there isn't one yet
;
KB_PEEK:
	LD	A,KC_PEEK
	OUT	(P_KBD),A	; send peek
KB_PEE2:
	CALL	KB_INP		; wait until its done
	CP	KD_PEEK
	JR	NC,KB_PEE2
	RET
;
; Get the next available keycode
; Wait until it appears
;
KB_GET:
	LD	A,KC_PEEK
	OUT	(P_KBD),A	; send peek
KB_GET2:
	CALL	KB_INP		; wait until its done
	CP	KD_PEEK
	JR	NC,KB_GET2
	CP	KD_NONE		; no keycode as yet
	JR	Z,KB_GET2
	RET
;
; Consume the keycode
;
KB_NEXT:
	LD	A,KC_NEXT
	OUT	(P_KBD),A	; send next
KB_NEX2:
	CALL	KB_INP		; wait until its down
	CP	KD_NEXT
	JR	NZ,KB_NEX2
	RET
;
; Input from the keyboard port
; The ARM chip is running on a different clock to the Z80
; so the value on the port could change whilst we look at it
; (which means we could see a mix of old and new bits in the byte)
; so keep reading it until we get the same value twice
;
KB_INP:	IN	A,(P_KBD)
KB_INP2:
	LD	C,A
	IN	A,(P_KBD)
	CALL	SHOWIN
	CP	C
	JR	NZ,KB_INP2
	RET
;
; SHOWIN - Show what we just input, to help debug the hardware
;
SHOWIN:	PUSH	HL
	PUSH	DE
	PUSH	BC
	PUSH	AF
	LD	DE,PATNAM+12*32+24
	CALL	VSETOT
	POP	AF
	PUSH	AF
	CALL	SHOWB
	POP	AF
	POP	BC
	POP	DE
	POP	HL
	RET
;
; SHOW - show a small region of memory from HL, to DE in VRAM
;
SHOW:	CALL	VSETOT
	LD	BC,8*4
SHOW2:	PUSH	BC
	LD	C,' '
	CALL	VDOUTP
	LD	A,(HL)
	CALL	SHOWB
	LD	C,' '
	CALL	VDOUTP
	INC	HL
	POP	BC
	DEC	BC
	LD	A,B
	OR	C
	JR	NZ,SHOW2
	RET
;
; SHOWW - Show HL as a word
;
SHOWW:	PUSH	HL
	LD	A,H
	CALL	SHOWB
	POP	HL
	LD	A,L
; fall
;
; SHOWB - Show A as a byte
;
SHOWB:	PUSH	AF
	SRL	A
	SRL	A
	SRL	A
	SRL	A
	CALL	SHOWH
	POP	AF
	AND	00FH
; fall
;
; SHOWH - show A (range 0..15) as a hex digit
;
SHOWH:	ADD	A,'0'
	CP	'9'+1
	JR	C,SHOWH2
	ADD	A,'A'-10-'0'
SHOWH2:	LD	C,A
	JP	VDOUTP
;
; VCOPY - copy from HL, to DE in VRAM, BC bytes
;
VCOPY:	CALL	VSETOT
	LD	D,B
	LD	E,C
VCOPY2:	LD	C,(HL)
	INC	HL
	CALL	VDOUTP
	DEC	DE
	LD	A,D
	OR	E
	JR	NZ,VCOPY2
	RET
;
; VSET - copy byte A, to DE in VRAM, BC bytes
;
VSET:	CALL	VSETOT
	LD	D,B
	LD	E,C
	LD	C,A
VSET2:	CALL	VDOUTP
	DEC	DE
	LD	A,D
	OR	E
	JR	NZ,VSET2
	RET
;
; Dummy vectors for now
;
RST08V:
RST10V:
RST18V:
RST18V:
RST20V:
RST28V:
RST30V:
RST38V:	
	RET
NMIV:	IN	A,(P_VDPCI)
	RETN
;
; CHARSET - Character set
;
CHARSET:
	INCLUDE	CHARSETC.INC
	INCLUDE	CHARSET.INC
	INCLUDE	CHARSETA.INC
	INCLUDE	CHARSETX.INC
;
	INCLUDE VIDEO.INC
;
	INCLUDE SOUND.INC
;
.DEPHASE

; PAD to 8KB
	ORG	02000H+100H

;
END

